# coding: utf-8

from typing import Sequence, TypeVar, Union, Generic
from io import StringIO
from graph import Graph, Subgraph, vertex_t, edge_t
from utils import find_list


# 可以是任意类型


T = TypeVar("T")


class vertex_map(Generic[T]):
    g: Union[Graph, Subgraph]
    name: str
    val: T = None

    def __init__(self, g: Union[Graph, Subgraph], name: str, val: T = None) -> None:
        self.g = g
        self.name = name
        self.init(val)
        # self.val = val

    def init(self, val: T = None):
        self.g.set_all_nodes_attr(self.name, val)

    # TODO print 为什么能输出，就是因为有这个 __str__ 魔法函数

    def __str__(self) -> str:
        out = StringIO()
        out.write(f"name: {self.name} ")
        for u in self.g.get_all_nodes():
            out.write(f"{u}: {self.at(u)}, ")
        out.write("\n")
        return out.getvalue()

    def at(self, u: vertex_t):
        return self.g.get_node_attr(u, self.name)

    def set(self, u: vertex_t, val: T):
        self.g.set_node_attr(u, self.name, val)

    def __getitem__(self, u: vertex_t):
        return self.at(u)

    def __setitem__(self, u: vertex_t, val: T):
        self.set(u, val)

    def values(self) -> Sequence[T]:
        return [self.at(u) for u in self.g.get_all_nodes()]

    # def add_vertex(self, u: vertex_t):
    # # u = self.g.add_node()
    # # if self.g.is_dummy_no
    # self.set(u, self.val)

    def contains(self, u: vertex_t):
        return self.g.has_node(u)

    def clear(self):
        self.g.remove_all_nodes_attr(self.name)

    def update(self, val: T = None):
        self.g.set_all_nodes_attr(self.name, val, update_mode=True)

    def size(self) -> int:
        return len(self.g.get_all_nodes())

    # def delete_nodes(self, nodes):
    #     return self.g.delete_nodes(nodes)


class edge_map(Generic[T]):
    g: Union[Graph, Subgraph]
    name: str
    val: T = None

    def __init__(self, g: Union[Graph, Subgraph], name: str, val: T = None) -> None:
        self.g = g
        self.name = name
        self.init(val)
        # self.val = val

    def init(self, val: T = None):
        self.g.set_all_edges_attr(self.name, val)

    # TODO print 为什么能输出，就是因为有这个 __str__ 魔法函数
    # def __str__(self) -> str:
    #     out = StringIO()
    #     out.write(f"name: {self.name} ")
    #     for u in self.g.get_all_nodes():
    #         out.write(f"{u}: {self.at(u)}, ")
    #     out.write("\n")
    #     return out.getvalue()

    def at(self, e: edge_t):
        return self.g.get_edge_attr(e, self.name)

    def set(self, e: edge_t, val: T):
        self.g.set_edge_attr(e, self.name, val)

    def __getitem__(self, e: edge_t):
        return self.at(e)

    def __setitem__(self, e: edge_t, val: T):
        self.set(e, val)

    def values(self) -> Sequence[T]:
        return [self.at(e) for e in self.g.get_all_edges()]

    def contains(self, e: edge_t):
        return self.g.get_edge_uv_tuple(e) is not None

    def clear(self):
        self.g.remove_all_edges_attr(self.name)

    def update(self, val: T = None):  # 新增节点属性是none 的话再给它加属性
        self.g.set_all_edges_attr(self.name, val, update_mode=True)

    def size(self) -> int:
        return len(self.g.get_all_edges())

    # def delete_nodes(self, nodes):
    #     return self.g.delete_nodes(nodes)


class edge_set:
    data: vertex_map[Sequence[vertex_t]]
    # data: vertex_map[Sequence[vertex_t]]

    def __init__(self, g: Union[Graph, Subgraph], name: str, val: T = None):

        self.data = vertex_map(g, name, val)

    def __str__(self) -> str:
        return str(self.data)

    def contains(self, u: vertex_t, v: vertex_t):
        return self.data.contains(u) and v in self.data[u]

    def insert(self, u: vertex_t, v: vertex_t):
        # self.data.add_vertex(u)
        # print(u, self.data[u], v, id(self.data[u]))
        self.data[u].append(v)

    def remove(self, u: vertex_t, v: vertex_t):
        if not self.data.contains(u):
            return False
        it = find_list(self.data[u], v)
        if it == -1:
            return False
        del self.data[u][it]
        return True
